/*
 *      Author: Guannan Ma
 *      @mythmgn
 *      Whatever license applied
 */

#include <pthread.h>
#include <time.h>
#include <stdarg.h>
#include <string.h>

#include "base.h"

struct _LOG_INFO{
	FILEW logFileW;
	LOG_LEVEL logLevel;
	int lock;
};

struct _LOG_INFO *_logger_info = NULL;

BOOL initLog(const LOG_LEVEL logLevel, const char *logFilePath){
	ASSERT(logFilePath);
	ASSERT(logLevel>=0);

    if (NULL==(_logger_info = (struct _LOG_INFO*)malloc(sizeof(struct _LOG_INFO))))
        logToStd("Mem malloc failed");
	strcpy(_logger_info->logFileW.fname, logFilePath);

	_logger_info->logLevel = logLevel;
	if( NULL == (_logger_info->logFileW.fp = fopen(logFilePath, "a+")) ){
        return FALSE;
    }else{
	    return TRUE;
    }
}


char*
getSTDLogDIR() {
	ASSERT(_logger_info);
	ASSERT(_logger_info->logFileW.fname);

	return _logger_info->logFileW.fname;
}
static int
checkWhetherLogIt(LOG_LEVEL level) {
    if (level>_logger_info->logLevel)
    	return 0;
    else
    	return 1;

}
static BOOL _logIt_(const char *fName, const int lineNo, int logger,const LOG_LEVEL logLevel,char *fmt,va_list stackptr){
        /*
    fmt supports %d %s %f %ld %lf
    */
    FILEW fw;
    char *fname;
    char tmStr[24];

    //va_list stackptr;

    int i;

    switch (checkWhetherLogIt(logLevel)) {
    case 1:
        goto logit;
    case 0:
        return TRUE;
    }

logit:

    switch(logger){
        case LOGGER_STD:
            fname=getSTDLogDIR();
            break;
        case LOGGER_PLUGIN:
            fname=getPluginLogDIR();
            if(NULL==fname)
                _logIt_(fName, lineNo, LOGGER_STD,LOG_ERROR,"Cannot get plugin log DIR. Will use the wasd.log instead.",stackptr);
            break;
    }

    if (NULL!=fname) {
        strcpy(fw.fname,fname);
    }
    if (NULL!=(fw.fp=fopen(fw.fname,"a+"))) {
        time_t tt;
        memset(tmStr,'\0',sizeof(tmStr));
        getStrTimeNow(tmStr,&tt);
        fprintf(fw.fp,"%s %ld",tmStr,tt);
        switch (logLevel) {
        case LOG_DEBUG:
            fprintf(fw.fp,"\tDEBUG");
            break;
        case LOG_INFO:
            fprintf(fw.fp,"\tINFO");
            break;
        case LOG_ERROR:
            fprintf(fw.fp,"\tERROR");
            break;
        }
    } else {
        logToStd("Openning log file failed. Plz check it out");
        return FALSE;
    }

    fprintf(fw.fp, " \t[%s:%d] \t", fName, lineNo);

    for(i=0; fmt[i]; i++) {
        if('%'==fmt[i]) {
            if(!fmt[++i]) {
                fputc('%', fw.fp);
                break;
            } else {
                switch(fmt[i]) {
                case '%':
                    fputc('%',fw.fp);
                    break;
                case 'd':
                    fprintf(fw.fp,"%d",va_arg(stackptr,int));
                    break;
                case 'f':
                    fprintf(fw.fp,"%g",va_arg(stackptr,double));
                    break;
                case 's':
                    fprintf(fw.fp,"%s",va_arg(stackptr,char *));
                    break;
                case 'l':
                    i++;
                    ASSERT(fmt[i]);
                    if('f'==fmt[i]) {
                        fprintf(fw.fp,"%lf",va_arg(stackptr,double));
                    }
                    if('d'==fmt[i]) {
                        fprintf(fw.fp,"%ld",va_arg(stackptr,long));
                    }
                    break;
                Default:
                    break;
                }
            }
            continue;
        } else {
            fputc(fmt[i],fw.fp);
        }

    }

    //va_end(stackptr);

    fputc('\n',fw.fp);
    fclose(fw.fp);
    return TRUE;

failAndClose:
    logToStd("Plz check the log level parameter in conf file.");
    fclose(fw.fp);
    return FALSE;
}
BOOL
logIt(const char *fName, const int lineNo, int logLevel, char *format, ...){

	static pthread_mutex_t mutex;
	int ret;
	ret = pthread_mutex_lock(&mutex);

	ASSERT(fName);
	ASSERT(format);

    va_list stackptr;
    BOOL rev;

    va_start(stackptr,format);
    rev=_logIt_(fName, lineNo, LOGGER_STD,logLevel,format,stackptr);
    va_end(stackptr);

    pthread_mutex_unlock(&mutex);

    return rev;
}

BOOL
logToStd(char *strings) {
    fprintf(stdout, "Message: %s\n",strings);
    return TRUE;
}

